/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ar.edu.unicen.twitter.suggest.backend.dtos;

import ar.edu.unicen.twitter.suggest.backend.recommendation.crawling.Recolector;
import ar.edu.unicen.twitter.suggest.commons.dtos.Usuario;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Alex
 */
public class RecommendationReport {

    public static final int POSICION_NO_ENCONTRADO = -1;
    public static final int METODO_AMIGOS = 1;
    public static final int METODO_FUENTES = 2;
    public static final int METODO_UNION = 3;
    public static final int METODO_INTERSECCION = 4;
    
    private long id;
    private int metodo;
    private Usuario usuario;
    private long usuarioId;
    private long[] recomendacionIds;
    private Collection<Usuario> recomendacion;
    private float[] score;
    private long[] holdoutIds;
    private Collection<Usuario> holdout;
    private int cantidadFuentes;
    private int cantidadFuentesRestantes;
    private int cantidadFuentesRecuperadas;
    private int[] posicion;
    private int posicionPrimero;
    private int posicionUltimo;
    private int iteracion;
    private float posicionQ1;
    private float posicionMediana;
    private float posicionQ3;
    private float porcentajeRecuperados;
    private int recuentoNodos;
    private int recuentoHojas;
    private boolean permitirRedundancia;
    private long elapsedTime;
    private Date date;
    private int holdoutSize;
    private int holdinSize;
    
    private Recolector recolector;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public int getMetodo() {
        return metodo;
    }

    public void setMetodo(int metodo) {
        this.metodo = metodo;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
        this.setUsuarioId(usuario.getId());
    }

    public long[] getRecomendacionIds() {
        return recomendacionIds;
    }

    public void setRecomendacionIds(long[] recomendacion) {
        this.recomendacionIds = recomendacion;
    }

    public float[] getScore() {
        return score;
    }

    public void setScore(float[] score) {
        this.score = score;
    }

    public long[] getHoldoutIds() {
        return holdoutIds;
    }

    public void setHoldoutIds(long[] holdout) {
        this.holdoutIds = holdout;
    }

    public int[] getPosicion() {
        return posicion;
    }

    private float percentil(List<Integer> valores, double percentil){
        int size = valores.size();
        if (size % 2 != 0) {
            return (valores.get((int) (size * percentil))).floatValue();
        } else {
            return ((valores.get((int) (size * percentil - 1))).floatValue()
                    + (valores.get((int) (size * percentil))).floatValue()) / 2;
        }
    }

    public void setPosicion(int[] posicion) {
        this.posicion = posicion;
        List<Integer> posicionesValidas = new ArrayList<Integer>();
        for (int p = 0; p < posicion.length; ++p) {
            if (posicion[p] != POSICION_NO_ENCONTRADO) {
                posicionesValidas.add(posicion[p]);
            }
        }
        if (!posicionesValidas.isEmpty()) {
            Collections.sort(posicionesValidas);
            this.setPosicionPrimero(posicionesValidas.get(0));
            this.setPosicionUltimo(posicionesValidas.get(posicionesValidas.size()-1));
            this.setPosicionQ1(percentil(posicionesValidas,0.25));
            this.setPosicionMediana(percentil(posicionesValidas,0.5));
            this.setPosicionQ3(percentil(posicionesValidas,0.75));
            this.setPorcentajeRecuperados(((float)posicionesValidas.size())/posicion.length);
        }
    }

    public long getElapsedTime() {
        return elapsedTime;
    }

    public void setElapsedTime(long elapsedTime) {
        this.elapsedTime = elapsedTime;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    private static long[] getIds(Collection<Usuario> usuarios) {
        long[] array = new long[usuarios.size()];
        int d = 0;
        for (Usuario usuario : usuarios) {
            array[d++] = usuario.getId();
        }

        return array;
    }

    public Collection<Usuario> getRecomendacion() {
        return recomendacion;
    }

    public void setRecomendacion(Collection<Usuario> recomendacion) {
        this.recomendacion = recomendacion;
        this.recomendacionIds = getIds(recomendacion);
    }

    public Collection<Usuario> getHoldout() {
        return holdout;
    }

    public void setHoldout(Collection<Usuario> holdout) {
        this.holdout = holdout;
        this.holdoutIds = getIds(holdout);
    }

    public int getRecuentoNodos() {
        return recuentoNodos;
    }

    public void setRecuentoNodos(int recuentoNodos) {
        this.recuentoNodos = recuentoNodos;
    }

    public int getRecuentoHojas() {
        return recuentoHojas;
    }

    public void setRecuentoHojas(int recuentoHojas) {
        this.recuentoHojas = recuentoHojas;
    }

    public int getPosicionPrimero() {
        return posicionPrimero;
    }

    public void setPosicionPrimero(int posicionPrimero) {
        this.posicionPrimero = posicionPrimero;
    }

    public int getPosicionUltimo() {
        return posicionUltimo;
    }

    public void setPosicionUltimo(int posicionUltimo) {
        this.posicionUltimo = posicionUltimo;
    }

    public float getPosicionMediana() {
        return posicionMediana;
    }

    public void setPosicionMediana(float posicionMediana) {
        this.posicionMediana = posicionMediana;
    }

    public float getPorcentajeRecuperados() {
        return porcentajeRecuperados;
    }

    public void setPorcentajeRecuperados(float porcentajeRecuperados) {
        this.porcentajeRecuperados = porcentajeRecuperados;
    }

    public Recolector getRecolector() {
        return recolector;
    }

    public void setRecolector(Recolector recolector) {
        this.recolector = recolector;
    }

    public boolean isPermitirRedundancia() {
        return permitirRedundancia;
    }

    public void setPermitirRedundancia(boolean permitirRedundancia) {
        this.permitirRedundancia = permitirRedundancia;
    }

    public int getHoldoutSize() {
        return holdoutSize;
    }

    public void setHoldoutSize(int holdoutSize) {
        this.holdoutSize = holdoutSize;
    }

    public int getHoldinSize() {
        return holdinSize;
    }

    public void setHoldinSize(int holdinSize) {
        this.holdinSize = holdinSize;
    }

    public long getUsuarioId() {
        return usuarioId;
    }

    public void setUsuarioId(long usuarioId) {
        this.usuarioId = usuarioId;
    }

    public int getIteracion() {
        return iteracion;
    }

    public void setIteracion(int iteracion) {
        this.iteracion = iteracion;
    }

    public float getPosicionQ1() {
        return posicionQ1;
    }

    public void setPosicionQ1(float posicionQ1) {
        this.posicionQ1 = posicionQ1;
    }

    public float getPosicionQ3() {
        return posicionQ3;
    }

    public void setPosicionQ3(float posicionQ3) {
        this.posicionQ3 = posicionQ3;
    }   

    public int getCantidadFuentes() {
        return cantidadFuentes;
    }

    public void setCantidadFuentes(int cantidadFuentes) {
        this.cantidadFuentes = cantidadFuentes;
    }

    public int getCantidadFuentesRestantes() {
        return cantidadFuentesRestantes;
    }

    public void setCantidadFuentesRestantes(int cantidadFuentesRestantes) {
        this.cantidadFuentesRestantes = cantidadFuentesRestantes;
    }

    public int getCantidadFuentesRecuperadas() {
        return cantidadFuentesRecuperadas;
    }

    public void setCantidadFuentesRecuperadas(int cantidadFuentesRecuperadas) {
        this.cantidadFuentesRecuperadas = cantidadFuentesRecuperadas;
    }
    
}
